package cn.toolck.springmvc.spring.bean;

import cn.toolck.springmvc.spring.annotation.MySecurity;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @ClassName SecurityHandler
 * @Description 处理Security注解的
 * @Author Toolck Rin
 * @Date 2021/2/28 23:47
 * @Version 1.0
 **/
public class SecurityHandler {

    Map<String, Set<String>> securityNameList = new HashMap<>();
    private final String PERMISSION_FILED = "username";

    public void dealWithSecurity(Map<String, HandlerMethod> handlerMapping) {
        handlerMapping.forEach((key, handlerMethod) -> {
            Set<String> securityValueByMethod = getSecurityValueByMethod(handlerMethod.getMethod());
            securityNameList.put(key, securityValueByMethod);
        });
    }

    private Set<String> getSecurityValueByMethod(Method method) {
        Set<String> securityValue = getSecurityValue(method);
        Set<String> securityValueByClass = getSecurityValueByClass(method.getDeclaringClass());
        if (!securityValue.isEmpty()) {
            securityValueByClass.retainAll(securityValue);
        }
        return securityValueByClass;
    }

    private Set<String> getSecurityValueByClass(Class<?> aClass) {
        return getSecurityValue(aClass);
    }

    private Set<String> getSecurityValue(AnnotatedElement element) {
        if (!element.isAnnotationPresent(MySecurity.class)) {
            return Collections.EMPTY_SET;
        }
        MySecurity annotation = element.getAnnotation(MySecurity.class);
        return new HashSet<String>(Arrays.asList(annotation.value()));
    }

    public Map<String, Set<String>> getSecurityNameList() {
        return securityNameList;
    }

    public void setSecurityNameList(Map<String, Set<String>> securityNameList) {
        this.securityNameList = securityNameList;
    }

    public boolean hasPermissions(HttpServletRequest req) {
        String requestURI = req.getRequestURI();
        String permissionsUser = req.getParameter(PERMISSION_FILED);
        return securityNameList.get(requestURI).contains(permissionsUser);
    }
}
